package com.longsec.qq.utils;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

import javax.net.ssl.SSLContext;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.util.EntityUtils;

import com.longsec.qq.pojo.Rsp;

/**
 * Http工具
 * @author 		Mr.Huang
 * @version		2019年12月4日
 */
@SuppressWarnings("deprecation")
public class RequestUtil {

	static RequestConfig config =null;
	static SSLContext sslContext = null;
	
	/**
     * 信任SSL证书
     */
    static {
        try {
            sslContext = SSLContextBuilder.create().useProtocol(SSLConnectionSocketFactory.SSL).loadTrustMaterial((x, y) -> true).build();
            config = RequestConfig.custom().setConnectTimeout(5000).setSocketTimeout(5000).build();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
	 * 获取请求信息
	 * @param url		请求地址
	 * @param headers	请求头
     */ 
	public static HttpGet getHttpGet(String url,Header... headers){
		return getHttpGet(url, null, headers);
	}
	
	/**
	 * 获取请求信息
	 * @param url		请求地址
	 * @param proxy		代理
	 * @param headers	请求头
	 * @return
	 */ 
	public static HttpGet getHttpGet(String url,HttpHost proxy,Header... headers){
		// 创建Get请求
		HttpGet httpGet = new HttpGet(url);

		if (headers != null) {
			httpGet.setHeaders(headers);	
		}
		if (proxy != null) {
			RequestConfig config = RequestConfig.custom().setProxy(proxy).build();
			httpGet.setConfig(config);			
		}
		httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:70.0) Gecko/20100101 Firefox/70.0");
		httpGet.setHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
		httpGet.setHeader("Accept-Language","zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2");
		httpGet.setHeader("Accept-Encoding","gzip, deflate, br");
		httpGet.setHeader("Connection","keep-alive");
		return httpGet;
	}
	 
	
	/**
	 * 请求
	 * @param httpGet
	 * @return
	 * @throws Exception
	 */
	public static Rsp execute(HttpGet httpGet) throws Exception {
		CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config).setSSLContext(sslContext).setSSLHostnameVerifier((x, y) -> true).build();
		// 响应模型
		CloseableHttpResponse response = null;
		try {
			// 由客户端执行(发送)Get请求
			response = httpClient.execute(httpGet);
			// 从响应模型中获取响应实体
			if (response.getStatusLine().getStatusCode() == 200) {
				Header[] allHeaders = response.getAllHeaders();
				Map<String, String> cookies = getCookies(allHeaders);
				Map<String, String> headers = getHeaders(allHeaders);
				HttpEntity entity = response.getEntity();
				byte[] body = EntityUtils.toByteArray(entity);
				Rsp rsp = new Rsp(body, cookies);
				rsp.headers = headers;
				return rsp;
			}
			//响应状态码异常
			throw new RuntimeException(response.getStatusLine().toString());
		} catch (Exception e) { 
			throw e;
		} finally {
			try {
				// 释放资源
				if (httpClient != null) {
					httpClient.close();
				}
				if (response != null) {
					response.close();
				}
			} catch (IOException e) {
				throw e;
			}
		}
	}
	
	/**
	 * 提取响应Cookie
	 * @param allHeaders
	 * @return
	 */
	private static Map<String, String> getCookies(Header[] allHeaders){
		Map<String, String> cookies = new HashMap<String, String>();
		for (Header header : allHeaders) {
			if ("Set-Cookie".equalsIgnoreCase(header.getName())) {
				String[] val = header.getValue().split(";");
				for (String c : val) {
					String[] split = c.trim().split("=");
					if (split.length>1) {
						cookies.put(split[0], split[1]);	
					}
				}
			}
		}
		return cookies;
	}
	
	/**
	 * 提取响应头信息
	 * @param allHeaders
	 * @return
	 */
	private static Map<String, String> getHeaders(Header[] allHeaders){
		Map<String, String> headers = new HashMap<String, String>();
		for (Header header : allHeaders) {
			headers.put(header.getName(), header.getValue());
		}
		return headers;
	}
	
}